import threading
import json
from serial_connect import SerialPortMethod
from inventory import Inventory
import redis
import time
import subprocess

from util import send_mqtt_message, mqtt_status_callback, get_mac_address, set_cabinet_current_status, set_cabinet_current_order_status

from setting import DOOR_STATUS, NOW_ESP_SET, CABINET_CURRENT_LOCK_STATUS

from sound_playback import SoundPlayback

from camera import Camera

import logging

logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')

logger = logging.getLogger(__name__)


class OperationFlow: # 业务流程

    def __enter__(self):

        return self

    def __exit__(self, exc_type, exc_val, exc_tb):

        self.r.close()


    def __init__(self, orderid) -> None:

        '''业务流程'''

        self.orderid = orderid

        self.camera_obj = Camera(orderid)

        self.check_door_thread = threading.Thread(target=self.check_door)

        self.open_door_thread = threading.Thread(target=self.start_process)

        self.open_door_thread_is_running = False

        self.is_runing = False
        
        self.spm = SerialPortMethod()

        self.r = redis.Redis(host='localhost', port=6379, db=0)

        # 创建一个订阅者对象
        self.p = self.r.pubsub()

        # 订阅频道
        self.p.subscribe(DOOR_STATUS)

        self.listen_door_status() # 检查门锁㹜，关闭则开启业务结束流程


    def start_process(self): 
        '''开启业务流程
        1、 开门
        '''
        send_order_times = 0

        self.open_door_thread_is_running = True

        while self.open_door_thread_is_running:

            self.spm.open_door() 

            time.sleep(1)

            if send_order_times == 5:

                self.r.set(CABINET_CURRENT_LOCK_STATUS, "门锁异常")

                self.r.publish(DOOR_STATUS, 'Error')

                break

            send_order_times+=1

    def check_door(self): # 检查门锁状态

        self.is_runing = True

        while self.is_runing:

            self.spm.check_door() 

            time.sleep(1)

        self.end_process() # 业务流程结束

    
    def listen_door_status(self):

        # self.spm.close_door() # 发送关门指令等待客户关门  门锁自动吸合所以取消掉了

        self.open_door_thread.start()

        # 循环接收消息
        for message in self.p.listen():

            logger.info("door_status:{}".format(message))

            if message['type'] == 'message':

                logger.info("message['data'] == b'True': {}".format(message['data'] == b'True'))

                if message['data'] == b'LockOpen':

                    logger.info("门锁状态：打开")

                    # self.open_inventory_ui() # 打开盘点页面

                    self.close_ad_midea() # 关闭广告

                    SoundPlayback().open_door_sound_thread.start() # 播放声音

                    self.camera_obj.start_camera() # 开始录像

                    self.open_door_thread_is_running = False

                    set_cabinet_current_status("门锁已打开")

                    time.sleep(5)

                    self.check_door_thread.start() # 开启门锁状态检查线程

                elif message['data'] == b'True':

                    logger.info("门状态：开启中！")

                elif message['data'] == b'False':

                    logger.info("门锁状态：关闭！！")

                    self.is_runing = False

                    SoundPlayback().close_door_sound_thread.start()

                    self.camera_obj.stop_camera() # 关闭摄像头

                    set_cabinet_current_status("门已关闭")

                    break

                elif message['data'] == b'Error':

                    logger.error("门锁5次下发开门命令未返回状态")
                    
                    break

    def open_ad_midea(self): # 打开广告视频

        logger.info("打开广告视频")

        command = ['systemctl', 'restart', 'ad_media.service']

        subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

    def close_ad_midea(self): # 关闭广告视频

        logger.info("关闭广告视频")

        command = ['systemctl', 'stop', 'ad_media.service']

        subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        

    def open_inventory_ui(self): # 开打盘点UI界面

        logger.info("开打盘点UI界面")

        command = ['systemctl', 'restart', 'inventory_ui.service']

        subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

    def close_inventory_ui(self): # 开打盘点UI界面

        logger.info("关闭盘点UI界面")

        command = ['systemctl', 'stop', 'inventory_ui.service']

        subprocess.Popen(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)

    def delay_open_ad_midea(self):

        time.sleep(8)  # 延迟8秒

        set_cabinet_current_order_status("无任务")

        self.open_ad_midea()

    
    def send_now_esp_set_to_mqtt(self):

        '''发送now_esp_set到数据中心'''

        now_esp_set = self.r.smembers(NOW_ESP_SET)

        now_esp_list = [item.decode() for item in now_esp_set]

        msg = {
            "mac": get_mac_address(),
            "esp_list": now_esp_list
        }

        send_mqtt_message(message=json.dumps(msg), topic="rfid_cabinet/esp_list")

        return now_esp_list

    
    def end_process(self): 
        '''业务流程结束'''

        mqtt_status_callback("正在盘点") # 同步状态
        set_cabinet_current_status("正在盘点")

        with Inventory(self.orderid) as inv:

            inv.start_inventory() # 开启盘点

            if inv.sentry_scan_rfid(): # 监测扫描结果

                logger.info("盘点结束")

                mqtt_status_callback("盘点结束") # 同步状态

                self.send_now_esp_set_to_mqtt()

                set_cabinet_current_status("盘点结束")


                SoundPlayback().inventory_commpleted_sound_thread.start() 

                threading.Thread(target=self.delay_open_ad_midea).start()
                


        


if __name__ == "__main__":

    with OperationFlow() as o:

        pass